package org.hismig.shard.hibernate;

import java.sql.SQLException;
import java.util.Properties;

import org.hibernate.classic.Session;
import org.hismig.cfg.DBConnection;
import org.hismig.cfg.partition.ConfigurationHelper;
import org.hismig.migration.Context;
import org.hismig.utils.CheckTool;

/**
 * @declare: //TODO <br />
 *           This class created by Vansion.Hopihit on 2012-9-4 <br />
 *           <a href="mailto:vansionhopihit@gmail.com">Contact Me</a>
 * @version 1.0
 * @author Vansion.Hopihit
 * 
 */
public class LocalSessionFactory {

	private String dbName;

	private String[] mappingLocations;

	private Properties hibernateProperties;

	private int maxSessionFactoryCount = 5;

	private SessionFactoryWrapper[] cacheSessionFactories;

	private int current = 0;

	public void init() {

		if (null != cacheSessionFactories && cacheSessionFactories.length > 0) {

			for (SessionFactoryWrapper sessionFactoryWrapper : cacheSessionFactories) {
				sessionFactoryWrapper.close();
			}

			cacheSessionFactories = null;
		}

		cacheSessionFactories = new SessionFactoryWrapper[maxSessionFactoryCount];

	}

	public Session openSession(Context context) throws SQLException {

		DBConnection dbConnection = ConfigurationHelper.getDBConnection(dbName,
				context);

		CheckTool.checkNotNull(dbConnection);

		for (SessionFactoryWrapper cacheSessionFactory : cacheSessionFactories) {
			if (null != cacheSessionFactory
					&& cacheSessionFactory.judgeCondition(dbConnection)) {
				return cacheSessionFactory.openSession();
			}
		}

		return createSessionFactoryWrapper(dbConnection).openSession();
	}

	private SessionFactoryWrapper createSessionFactoryWrapper(
			DBConnection dbConnection) {

		SessionFactoryWrapper sessionFactoryWrapper = new SessionFactoryWrapper(
				dbConnection, mappingLocations, hibernateProperties);

		if (current <= maxSessionFactoryCount - 1) {

			cacheSessionFactories[current] = sessionFactoryWrapper;

			current++;
		} else {

			int releaseIndex = 0;

			for (int i = 1; i < cacheSessionFactories.length; i++) {

				if (cacheSessionFactories[i].getLastInvokeTime() < cacheSessionFactories[releaseIndex]
						.getLastInvokeTime()) {
					releaseIndex = i;
				}
			}
			cacheSessionFactories[releaseIndex].close();

			cacheSessionFactories[releaseIndex] = sessionFactoryWrapper;
		}

		return sessionFactoryWrapper;

	}
	public void setMappingLocations(String[] mappingLocations) {
		this.mappingLocations = mappingLocations;
	}

	public void setHibernateProperties(Properties hibernateProperties) {
		this.hibernateProperties = hibernateProperties;
	}

	public void setDbName(String dbName) {
		this.dbName = dbName;
	}

	public void setMaxSessionFactoryCount(int maxSessionFactoryCount) {
		this.maxSessionFactoryCount = maxSessionFactoryCount;
	}

}
